package com.cctc.juc.source.Bitc.Ecas.longadder;
/**
 * 【CAS “空自旋” 优化解决方案之 [分散竞争热点]】。
 * 问题分析：在高并发环境下，AtomicLong.value 变量其实是一个热点，也就是 N 个线程竞争一个热点。在竞争激烈的场景下，会导致很多线程不停的 “自旋” 重试，重试线程越多，就意味着 CAS 失败的概率越高，从而进入恶性的 CAS “空自旋” 状态，造成严重的 CPU 性能损耗，从而影响程序的性能。
 * 解决方案： “以空间换时间”，或者 [分散竞争热点]，或者 [排队争抢线程]，或者 [使用线程本地变量]。
 * [分散竞争热点] 在竞争激烈的场景下，我们可以将 AtomicLong.value 值分散到一个 Cell 数组中，不同的线程会命中到 Cell 数组的不同槽（Cell 元素）中，各个线程只对自己槽中的 Cell.value 值进行 CAS 操作，如果要获得完整的 value 值，只需要将各个槽中的变量值（Cell.value）累加起来，返回最终的累加结果即可。这样一来，热点就被分散了，冲突的概率就小了很多。
 * [分散竞争热点] 实现类之 LongAdder 源码解析：
 * LongAdder 核心方法：
 * - public void add(long update)，默认情况下将给定的 update 值更新至 Base 基础值，如果更新失败，说明产生了争用冲突，执行 longAccumulate 方法，将给定值相加至指定 Cell 单元格内，进行热点分散。
 * - public long sum()，如果要获得完整的 value 值，只需要将各个槽中的变量值（Cell.value）累加起来，返回最终的累加结果即可。
 * LongAdder 依赖于 Striped64 抽象（基）类完成 [分散竞争热点] 操作。
 * Striped64 类中定义了一个核心内部类 Cell 单元格，并基于此构建了一个 cells 数组，在竞争激烈的场景下，不同的线程（基于线程的哈希值）会命中到 Cell 数组的不同槽（Cell 元素）中，各个线程只对自己槽中的 Cell.value 值进行 CAS 操作，以达到 [分散竞争热点] 的效果。
 * Striped64 类的核心方法为 longAccumulate() 累加器，下面给出该方法的实现思路：
 * 1）首先，计算当前争用线程对应的哈希值，用于定位 cells 数组中的哈希槽；
 * 2）通过 CAS “自旋”，写入 update 更新数据：
 * - 如果 cells 数组还未完成初始化或正在扩容，将当前争用线程的 update 更新值直接累加到 base 基础值上，退出循环。
 * - 如果 cells 数组已经初始化，将当前争用线程的 update 更新数据写入到对应的 Cell 单元格中，一直到操作成功，退出循环。
 * 最后，如果要获得完整的 value 值，只需要调用 LongAdder.sum 方法，将各个槽中的变量值（Cell.value）累加起来，返回最终的累加结果即可。
 * [分散竞争热点] 性能分析：在较低的更新争用下，这两个类具有相似的特性。但在竞争激烈的情况下，[分散竞争热点] 的预期吞吐量要高得多。从对比实验的结果可以看出，在 CAS 争用最为激烈的场景下，LongAdder 的性能是 AtomicLong 性能的 8 倍。
 */